<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>深浅拷贝</title>
</head>

<body>
    <script>
        var father = { name: 'shangdi', age: 1000, job: ['teacher', 'cook'] };
        //浅拷贝函数
        function copy(obj) {
            var childs = {};
            for (var key in obj) {
                childs[key] = obj[key];
            }
            return childs;
        }
        var child = copy(father);
        console.log(child);    //{ name: 'shangdi', age: 1000 }
        // console.log(typeof child); //object

        //改变子对象的name属性，发现对父对象的name没有影响 哈哈！
        child.name = 'bangbang';
        console.log(father);   //{ name: 'shangdi', age: 1000 }
        console.log(child);    //{ name: 'bangbang', age: 1000 }

        //注意：这次改变子对象的job属性也就是改变数组,
        //发现对父对象的job竟然有影响,吓死宝宝了，那怎么办呢,那这个copy有什么用呢是吧！
        child.job.push('programer');
        console.log(father);   //{ name: 'shangdi',age: 1000,job: [ 'teacher', 'cook', 'programer' ] }
        console.log(child);    //{ name: 'shangdi',age: 1000,job: [ 'teacher', 'cook', 'programer' ] }
        console.log('-------------------------');


        // 深度拷贝就是把父对象拷贝到子对象上，而且两者的内存和以后的操作都互不影响的拷贝！
        var father1 = { name: 'shangdi', age: 1000, job: ['teacher', 'cook'] };
        function deepCopy(obj) {
            var o;
            switch (typeof obj) {
                case 'undefined': break;
                case 'string': o = obj + ''; break;
                case 'number': o = obj - 0; break;
                case 'boolean': o = obj; break;
                case 'object':
                    if (obj === null) {
                        o = null;
                    } else {
                        if (obj instanceof Array) {
                            o = [];
                            for (var i = 0, len = obj.length; i < len; i++) {
                                o.push(deepCopy(obj[i]));
                            }
                        } else {
                            o = {};
                            for (var k in obj) {
                                o[k] = deepCopy(obj[k]);
                            }
                        }
                    }
                    break;
                default:
                    o = obj; break;
            }
            return o;
        }

        var child1 = deepCopy(father1);
        console.log(child1);    //{ name: 'shangdi', age: 1000 }

        //改变子对象的name属性，发现对父对象的name没有影响 哈哈！
        child1.name = 'bangbang';
        console.log(father1);   //{ name: 'shangdi', age: 1000 }
        console.log(child1);    //{ name: 'bangbang', age: 1000 }

        //注意：这次改变子对象的job属性也就是改变数组,
        //发现对父对象的job竟然有影响,吓死宝宝了，那怎么办呢,那这个copy有什么用呢是吧！
        child1.job.push('programer');
        console.log(father1);   //{ name: 'shangdi',age: 1000,job: [ 'teacher', 'cook', 'programer' ] }
        console.log(child1);    //{ name: 'shangdi',age: 1000,job: [ 'teacher', 'cook', 'programer' ] }
        console.log('-------------------------');


        // 方法二：最简单的
        var father1 = { name: 'shangdi', age: 1000, job: ['teacher', 'cook'] };
        function deepCopy2(obj) {
            // console.log(JSON.stringify(obj)); // {"name":"shangdi","age":1000,"job":["teacher","cook"]}
            return JSON.parse(JSON.stringify(obj));
        }
        console.log(deepCopy2(father1));
        var child1 = deepCopy2(father1);
        console.log(child1);    //{ name: 'shangdi', age: 1000 }

        //改变子对象的name属性，发现对父对象的name没有影响 哈哈！
        child1.name = 'bangbang';
        console.log(father1);   //{ name: 'shangdi', age: 1000 }
        console.log(child1);    //{ name: 'bangbang', age: 1000 }

        //注意：这次改变子对象的job属性也就是改变数组,
        //发现对父对象的job竟然有影响,吓死宝宝了，那怎么办呢,那这个copy有什么用呢是吧！
        child1.job.push('programer');
        console.log(father1);   //{ name: 'shangdi',age: 1000,job: [ 'teacher', 'cook', 'programer' ] }
        console.log(child1);    //{ name: 'shangdi',age: 1000,job: [ 'teacher', 'cook', 'programer' ] }
        console.log('-------------------------');

        // 方法三：
        // function deepCopy(obj) {
        //     var newobj, obj;
        //     if (obj.constructor == Object) {
        //         newobj = new obj.constructor();
        //     } else {
        //         newobj = new obj.constructor(obj.valueOf());//valueOf()方法返回 Array 对象的原始值
        //     }
        //     for (var key in obj) {
        //         if (newobj[key] != obj[key]) {
        //             if (typeof (obj[key]) == 'object') {
        //                 newobj[key] = deepCopy(obj[key]);
        //             } else {
        //                 newobj[key] = obj[key];
        //             }
        //         }
        //     }
        //     newobj.toString = obj.toString;
        //     newobj.valueOf = obj.valueOf;
        //     return newobj;
        // }

        // 方法四：

        // var cloneObj = function (obj) {
        //     var str, newobj = obj.constructor === Array ? [] : {};
        //     if (typeof obj !== 'object') {
        //         return;
        //     } else if (window.JSON) {
        //         str = JSON.stringify(obj), //系列化对象
        //             newobj = JSON.parse(str); //还原
        //     } else {
        //         for (var i in obj) {
        //             newobj[i] = typeof obj[i] === 'object' ?
        //                 cloneObj(obj[i]) : obj[i];
        //         }
        //     }
        //     return newobj;
        // };

        // 方法五：(JavaScript面向对象编程指南)

        // function deepCopy(p, c) {
        //     c = c || {};
        //     for (var i in p) {
        //         if (p.hasOwnProperty(i)) {
        //             if (typeof p[i] === 'object') {
        //                 c[i] = Array.isArray(p[i]) ? [] : {};
        //                 deepCopy(p[i], c[i]);
        //             } else {
        //                 c[i] = p[i];
        //             }
        //         }
        //     }
        //     return c;
        // }

    </script>
</body>

</html>